/* ================================================================
*   Copyright (C) 2020 All rights reserved.
*
*   文件名称：xproto.cpp
*   创 建 者：xunmenglong
*   创建日期：2020年12月03日
*   描    述：
*
================================================================ */


#ifndef XPROTO_CPP
#define XPROTO_CPP

#include "xproto.h"

void xproto::_init_type_map() {
    _TYPE_MAP.insert(pair<string, int>("int", XP_TYPE_INT));
    _TYPE_MAP.insert(pair<string, int>("uint", XP_TYPE_UINT));
    _TYPE_MAP.insert(pair<string, int>("int64", XP_TYPE_INT64));
    _TYPE_MAP.insert(pair<string, int>("uint64", XP_TYPE_UINT64));
    // 目前将8和16位的int都存为int
    _TYPE_MAP.insert(pair<string, int>("int8", XP_TYPE_INT));
    _TYPE_MAP.insert(pair<string, int>("uint8", XP_TYPE_UINT));
    _TYPE_MAP.insert(pair<string, int>("int16", XP_TYPE_INT));
    _TYPE_MAP.insert(pair<string, int>("uint16", XP_TYPE_UINT));
    // float也存为double
    _TYPE_MAP.insert(pair<string, int>("float", XP_TYPE_DOUBLE));
    _TYPE_MAP.insert(pair<string, int>("double", XP_TYPE_DOUBLE));
    _TYPE_MAP.insert(pair<string, int>("string", XP_TYPE_STRING));
    _TYPE_MAP.insert(pair<string, int>("object", XP_TYPE_OBJECT));
    _TYPE_MAP.insert(pair<string, int>("array", XP_TYPE_ARRAY));
}

int xproto::init(const char * schema_str) {
    _init_type_map();
    Document d;
    if (d.Parse(schema_str).HasParseError()) {
        LOG(ERROR) << "parse schema_str fail";
        return -1;
    }

    _schema = _parse_schema(d);
    if (_schema == NULL) {
        LOG(ERROR) << "parse schema fail";
        return -1;
    }
    return 0;
}

schema_t * xproto::_alloc_schema_t(int fields_num) {
    schema_t * schema = (schema_t *)malloc(sizeof(schema_t));
    if (schema == NULL) {
        LOG(ERROR) << "malloc schema_t fail";
        return NULL;
    }
    schema->fields_num = fields_num;
    // 全部置0
    schema->fields = (field_t *)calloc(sizeof(field_t)*fields_num, 1);
    schema->idx_map = new FieldsIdxMap();
    if (schema->idx_map == NULL) {
        LOG(ERROR) << "malloc fields idx map fail";
        return NULL;
    }
    int ret = schema->idx_map->init(fields_num);
    if (ret != 0) {
        LOG(ERROR) << "idx_map init fail";
        return NULL;
    }
    return schema;
}

schema_t * xproto::_parse_schema(Value &v) {
    if (!v.IsObject()) {
        // 如果不是Object就直接返回NULL
        return NULL;
    }

    int fields_num = v.Size();
    schema_t * schema = _alloc_schema_t(fields_num);

    int i = 0;
    for (Value::ConstMemberIterator iter = v.MemberBegin();
            iter != v.MemberEnd(); ++iter) {
        const char * field_name = iter->name.GetString();
        uint64_t field_key = XXH64(field_name, strlen(field_name), 0);
        if (!iter->value.HasMember("idx") ||
                !iter->value.HasMember("type")) {
            LOG(ERROR) << field_name << " do not have idx or type";
            return NULL;
        }
        int idx = iter->value["idx"].GetInt();
        field_t * cur_field = &(schema->fields[idx]);
        cur_field->idx = idx;
        schema->idx_map->insert(field_key, idx);

        // 填充cur_field对象
        strcpy(cur_field->name, field_name);
        if (!iter->value["idx"].IsInt()) {
            LOG(ERROR) << field_name << " idx is not a int";
            return NULL;
        }
        cur_field->type = _TYPE_MAP[iter->value["type"].GetString()];
        if (cur_field->type == 0) {
            LOG(ERROR) << field_name << " type is illegal";
            return NULL;
        }
        cur_field->is_option = 1;
        if (iter->value.HasMember("is_option") &&
                iter->value["is_option"].IsInt()) {
            cur_field->is_option = iter->value["is_option"].GetInt();
        }
        // 如果是普通类型, 那么到这里已经解析完毕了, 如果是复杂类型, 就需要递归了
        if (cur_field->type == XP_TYPE_OBJECT) {
            // 如果是object, 就需要递归了
            cur_field->schema = _parse_schema(v[field_name]["schema"]);
            if (cur_field->schema == NULL) {
                LOG(ERROR) << field_name << " parse object schema fail";
                return NULL;
            }
        } else if (cur_field->type == XP_TYPE_ARRAY) {
            cur_field->element_type = _TYPE_MAP[iter->value["element_type"].GetString()];
            if (cur_field->element_type == 0) {
                LOG(ERROR) << field_name << " array's element_type is illegal";
                return NULL;
            }
            if (cur_field->element_type == XP_TYPE_OBJECT) {
                // 如果是对象数组, 就需要递归
                cur_field->schema = _parse_schema(v[field_name]["schema"]);
                if (cur_field->schema == NULL) {
                    LOG(ERROR) << field_name << " parse array schema fail";
                    return NULL;
                }
            }
        }
        i++;
    }
    return schema;
}

int xproto::serialize(const char * object_json_str, char * out_data,
        char * head_data, char * body_data) {
    Document d;
    if (d.Parse(object_json_str).HasParseError()) {
        LOG(ERROR) << "parse object json fail";
        return -1;
    }
    return serialize(d, out_data, head_data, body_data);
}

int xproto::serialize(Document &d, char * out_data,
        char * head_data, char * body_data) {
    int * head_ptr = (int *)head_data;

    pair<int, int> ret = _parse_object(d, _schema, head_ptr, body_data);

    int head_len = ret.first*sizeof(int);
    int body_len = ret.second;

    if (body_len == -1) {
        // 解析错误
        LOG(ERROR) << "serialize str to binary fail";
        return -1;
    }

    package_head_t p_head;
    p_head.total_len = head_len+body_len;
    p_head.head_len = head_len;

    memcpy(out_data, &p_head, sizeof(package_head_t));
    out_data += sizeof(package_head_t);
    memcpy(out_data, head_data, head_len);
    out_data += head_len;
    memcpy(out_data, body_data, body_len);

    return sizeof(package_head_t)+head_len+body_len;
}

pair<int,int> xproto::_parse_object(Value &v, schema_t * schema, int * head_ptr,
        char * body_ptr, int body_offset) {
    pair<int, int> err = pair<int, int>(-1, -1);
    if (!v.IsObject()) {
        LOG(ERROR) << "v is not an object";
        return err;
    }

    // 记录header占了多少空间
    int head_offset = schema->fields_num;

    int * start_head_ptr = head_ptr;
    char * start_body_ptr = body_ptr;

    for (int i=0; i<schema->fields_num; i++) {
        field_t cur_field = schema->fields[i];
        char * field_name = cur_field.name;
        // 首先判断该字段是否存在
        if (!v.HasMember(field_name)) {
            if (cur_field.is_option) {
                // 可选字段, 将header位置设置为0
                start_head_ptr[i] = -1;
                continue;
            } else {
                // 非可选字段
                LOG(ERROR) << field_name << " is not exists, and is not option";
                return err;
            }
        }

        int type = cur_field.type;
        if (type != XP_TYPE_OBJECT && type != XP_TYPE_ARRAY) {
            // 普通字段
            const char * value_ptr = NULL;
            int value_len = 0;

            if (type == XP_TYPE_INT) {
                if (!v[field_name].IsInt()) {
                    LOG(ERROR) << field_name << " is not int";
                    return err;
                }
                int value = v[field_name].GetInt();
                value_ptr = (char *)&value;
                value_len = sizeof(int);
            } else if (type == XP_TYPE_UINT) {
                if (!v[field_name].IsUint()) {
                    LOG(ERROR) << field_name << " is not uint";
                    return err;
                }
                uint value = v[field_name].GetUint();
                value_ptr = (char *)&value;
                value_len = sizeof(uint);
            } else if (type == XP_TYPE_INT64) {
                if (!v[field_name].IsInt64()) {
                    LOG(ERROR) << field_name << " is not int64";
                    return err;
                }
                int64_t value = v[field_name].GetInt64();
                value_ptr = (char *)&value;
                value_len = sizeof(int64_t);
            } else if (type == XP_TYPE_UINT64) {
                if (!v[field_name].IsUint64()) {
                    LOG(ERROR) << field_name << " is not uint64";
                    return err;
                }
                uint64_t value = v[field_name].GetUint64();
                value_ptr = (char *)&value;
                value_len = sizeof(uint64_t);
            } else if (type == XP_TYPE_DOUBLE) {
                if (!v[field_name].IsDouble()) {
                    LOG(ERROR) << field_name << " is not double";
                    return err;
                }
                double value = v[field_name].GetDouble();
                value_ptr = (char *)&value;
                value_len = sizeof(double);
            } else if (type == XP_TYPE_STRING) {
                if (!v[field_name].IsString()) {
                    LOG(ERROR) << field_name << " is not string";
                    return err;
                }
                const char * value = v[field_name].GetString();
                value_ptr = (char *)value;
                value_len = strlen(value) + 1;
            }

            if (value_ptr == NULL) {
                LOG(ERROR) << "value_ptr is null";
                return err;
            }

            memcpy(body_ptr, value_ptr, value_len);
            // 直接设置为body的位置
            start_head_ptr[i] = body_offset;

            // body游标移动
            body_ptr += value_len;
            body_offset += value_len; //?

        } else if (type == XP_TYPE_OBJECT) {
            // 对象字段
            pair<int, int> ret = _parse_object(v[field_name], cur_field.schema, 
                    start_head_ptr+head_offset, body_ptr, body_offset);
            int cur_head_len = ret.first;
            int cur_body_len = ret.second;

            if (cur_head_len < 0) {
                LOG(ERROR) << field_name << " parse object fail";
                return err;
            }

            start_head_ptr[i] = head_offset; //指向头部
            head_offset += cur_head_len; // 头部长度扩展

            body_ptr += cur_body_len;
            body_offset += cur_body_len;

        } else if (type == XP_TYPE_ARRAY) {
            // 数组字段
            pair<int, int> ret = _parse_array(v[field_name], cur_field.schema,
                    cur_field.element_type, start_head_ptr+head_offset, body_ptr, body_offset);
            int cur_head_len = ret.first;
            int cur_body_len = ret.second;

            if (cur_head_len < 0) {
                LOG(ERROR) << field_name << " parse array fail";
                return err;
            }

            start_head_ptr[i] = head_offset+1; //指向头部的下一个位置(跳过长度)
            head_offset += cur_head_len; // 扩展头部

            body_ptr += cur_body_len;
            body_offset += cur_body_len;

        }
    }

    return pair<int, int>(head_offset, body_ptr-start_body_ptr);
}

pair<int, int> xproto::_parse_array(Value &v, schema_t * schema, int element_type,
        int * head_ptr, char * body_ptr, int body_offset) {
    pair<int, int> err = pair<int, int>(-1, -1);
    if (!v.IsArray()) {
        LOG(ERROR) << "is not an array";
        return err;
    }
    int size = (int)v.Size();

    // 首先记录长度
    head_ptr[0] = size;
    head_ptr++;
    // 记录header占了空间
    int head_offset = size;
    int * start_head_ptr = head_ptr;
    char * start_body_ptr = body_ptr;
    if (element_type != XP_TYPE_OBJECT) {
        for (int i=0; i<size; i++) {
            const char * value_ptr = NULL;
            int value_len = 0;

            if (element_type == XP_TYPE_INT) {
                if (!v[i].IsInt()) {
                    LOG(ERROR) << i << " is not int";
                    return err;
                }
                int value = v[i].GetInt();
                value_ptr = (char *)&value;
                value_len = sizeof(int);
            } else if (element_type == XP_TYPE_UINT) {
                if (!v[i].IsUint()) {
                    LOG(ERROR) << i << " is not uint";
                    return err;
                }
                uint value = v[i].GetUint();
                value_ptr = (char *)&value;
                value_len = sizeof(uint);
            } else if (element_type == XP_TYPE_INT64) {
                if (!v[i].IsInt64()) {
                    LOG(ERROR) << i << " is not int64";
                    return err;
                }
                int64_t value = v[i].GetInt64();
                value_ptr = (char *)&value;
                value_len = sizeof(int64_t);
            } else if (element_type == XP_TYPE_UINT64) {
                if (!v[i].IsUint64()) {
                    LOG(ERROR) << i << " is not uint64";
                    return err;
                }
                uint64_t value = v[i].GetUint64();
                value_ptr = (char *)&value;
                value_len = sizeof(uint64_t);
            } else if (element_type == XP_TYPE_DOUBLE) {
                if (!v[i].IsDouble()) {
                    LOG(ERROR) << i << " is not double";
                    return err;
                }
                double value = v[i].GetDouble();
                value_ptr = (char *)&value;
                value_len = sizeof(double);
            } else if (element_type == XP_TYPE_STRING) {
                if (!v[i].IsString()) {
                    LOG(ERROR) << i << " is not string";
                    return err;
                }
                const char * value = v[i].GetString();
                value_ptr = (char *)value;
                value_len = strlen(value) + 1;
            }

            if (value_ptr == NULL) {
                LOG(ERROR) << "value_ptr is null";
                return err;
            }

            memcpy(body_ptr, value_ptr, value_len);
            start_head_ptr[i] = body_offset;

            body_ptr += value_len;
            body_offset += value_len;
        }
    } else {
        head_ptr += size; // 留出二级索引空间
        for (int i=0; i<size; i++) {
            pair<int, int> ret = _parse_object(v[i], schema, head_ptr, body_ptr, body_offset);

            int cur_head_len = ret.first;
            int cur_body_len = ret.second;

            if (cur_head_len < 0) {
                LOG(ERROR) << i << " object parse error";
                return err;
            }

            start_head_ptr[i] = head_offset;
            head_offset += cur_head_len;
            head_ptr += cur_head_len;

            body_ptr += cur_body_len;
            body_offset += cur_body_len;
        }
    }

    return pair<int, int>(head_offset+1, body_ptr-start_body_ptr);
}

int xprotogetter::get_strs_by_fields(int * handler, field_t ** fields, int fields_len,
        deque<string> & result) {
    field_t * last_field = fields[fields_len-1];
    if (last_field->type == XP_TYPE_OBJECT) {
        LOG(ERROR) << "cannot support object type";
        return -1;
    }
    if (last_field->type == XP_TYPE_ARRAY &&
            last_field->element_type == XP_TYPE_OBJECT) {
        LOG(ERROR) << "cannot support array object type";
        return -1;
    }
    // 最后是普通类型, 就开始获取值
    for (int i=0; i<fields_len; i++) {
        field_t * cur_field = fields[i];

        if (cur_field->type == XP_TYPE_OBJECT) {
            handler = o1(handler, cur_field->idx);
            if (handler == NULL) {
                break;
            }
        } else if (cur_field->type == XP_TYPE_ARRAY) {
            handler = o1(handler, cur_field->idx);
            if (handler == NULL) {
                break;
            }
            if (cur_field->element_type == XP_TYPE_OBJECT) {
                // 复杂类型
                int size = l0(handler);
                for (int j=0; j<size; j++) {
                    int * cur_handler = o1(handler, j);
                    // 递归搞
                    int ret = get_strs_by_fields(cur_handler, fields+i+1,
                            fields_len-i-1, result);
                    if (ret != 0) {
                        LOG(ERROR) << "get object arr strs fail: " << i << "," << j;
                        return -1;
                    }
                }
                // 因为已经将后面的数据已经处理过了, 所以可以直接退出了
                break;
            } else {
                // 普通类型
                int size = l0(handler);
                for (int j=0; j<size; j++) {
                    string tmp_result;
                    int ret = _get_simple_type_str(v1(handler, j),
                            cur_field->element_type, tmp_result, false);
                    if (ret != 0) {
                        LOG(ERROR) << "get simple str fail: " << i << "," << j;
                        return -1;
                    }
                    result.push_back(tmp_result);
                }
            }
        } else {
            // 普通类型, 往结果里面塞值即可
            string tmp_result;
            int ret = _get_simple_type_str(v1(handler, cur_field->idx),
                    cur_field->type, tmp_result, false);
            if (ret != 0) {
                LOG(ERROR) << "get simple str fail: " << i;
                return -1;
            }
            result.push_back(tmp_result);
        }
    }
    return 0;
}

int xprotogetter::get_fields_by_str(schema_t * schema, const char * str,
        field_t ** fields, int * fields_len) {
    field_t ** cur_field_ptr = fields;
    xstr_spliter iter(str, ".");
    while (!iter.is_end()) {
        xcharpos cur_name = iter.get_next();
        bool is_str_arr = false;
        if (cur_name.str[cur_name.len-1] == ']' &&
                cur_name.str[cur_name.len-2] == '[') {
            is_str_arr = true;
            cur_name.len -= 2;
        }
        uint64_t field_key = XXH64(cur_name.str, cur_name.len, 0);
        int * cur_idx = schema->idx_map->seek(field_key);
        if (cur_idx == NULL) {
            LOG(ERROR) << "cannot find key: " << cur_name.to_string();
            return -1;
        }
        field_t * cur_field = schema->fields + *cur_idx;
        if (is_str_arr && cur_field->type != XP_TYPE_ARRAY) {
            LOG(ERROR) << "cur key is not an array: " << cur_name.to_string();
            return -1;
        }

        // 将当前field加入结果集合当中
        *cur_field_ptr = cur_field;
        cur_field_ptr++;

        if (cur_field->type == XP_TYPE_OBJECT) {
            // 对象类型, 还要继续
            schema = cur_field->schema;
        } else if (cur_field->type == XP_TYPE_ARRAY) {
            if (cur_field->element_type == XP_TYPE_OBJECT) {
                // 对象数组
                schema = cur_field->schema;
            } else {
                // 简单类型数组
                break;
            }
        } else {
            // 普通类型
            break;
        }
    }


    if (!iter.is_end()) {
        LOG(ERROR) << "str already meet simple type field but have more fields";
        return -1;
    }

    *fields_len = cur_field_ptr - fields;

    return 0;
}

/**
 * @brief: 根据输入的key_str返回idx数组
 *
 * @param schema    [in]  即xproto根据schema.json解析出来的对象
 * @param key_str   [in]  输入的用于解析的字符串, 输入key值用"."做层级分隔
 * @param idx_arr   [out] 存储idx的数组
 * @param arr_len   [out] 数组长度
 * @param field_t*  [out] 该field的一些基本信息输出
 */
int xprotogetter::get_idxs_by_str(schema_t * schema, xcharpos * key_str_info, int * idx_arr,
        int * arr_len, field_t ** field) {
    if (schema == NULL) {
        LOG(ERROR) << "schema is not NULL";
        return -1;
    }
    schema_t * cur_schema = schema;
    int result_arr_len = 0;
    field_t * result_field = NULL;

    int last_start_pos = 0;
    const char * key_str = key_str_info->str;
    int total_key_len = key_str_info->len;

    for(int pos=0; pos<total_key_len; pos++) {
        char c = key_str[pos];
        if (c == '.' || pos == total_key_len-1) {
            if (pos == total_key_len-1) {
                pos++;
            }
            if (pos > last_start_pos) {
                const char * key_ptr = key_str+last_start_pos;
                int key_len = pos-last_start_pos;

                xcharpos cur_key;
                cur_key.str = key_ptr;
                cur_key.len = key_len;

                if (cur_schema == NULL) {
                    LOG(ERROR) << "cur_schema is null: " << build_xcharpos_str(&cur_key);
                    return -1;
                }
                int arr_offset = -1;
                if (key_ptr[key_len-1] == ']') {
                    // 是个数组表达
                    for (int i=key_len-2; i>=0; i--) {
                        if (key_ptr[i] == '[') {
                            arr_offset = i;
                        }
                    }

                    if (arr_offset == -1) {
                        LOG(ERROR) << "array expr do not have '['" << build_xcharpos_str(&cur_key);
                        return -1;
                    }

                    if (arr_offset+2 >= key_len) {
                        LOG(ERROR) << "array expr have empty []: " << build_xcharpos_str(&cur_key);
                        return -1;
                    }

                    cur_key.len = arr_offset;
                    arr_offset = atoi(key_ptr+arr_offset+1);
                }

                uint64_t field_key = XXH64(cur_key.str, cur_key.len, 0);
                int * cur_idx = cur_schema->idx_map->seek(field_key);
                if (cur_idx == NULL) {
                    // LOG(ERROR) << "cannot find key: " << build_xcharpos_str(&cur_key);
                    return -2;
                }
                // 输出
                idx_arr[result_arr_len] = *cur_idx;
                result_arr_len++;
                if (arr_offset != -1) {
                    // 如果是数组, 就加一个int上去
                    idx_arr[result_arr_len] = arr_offset;
                    result_arr_len++;
                }
                result_field = cur_schema->fields + *cur_idx;
                cur_schema = result_field->schema;

                if (result_field->type == XP_TYPE_ARRAY && c == '.' && arr_offset == -1) {
                    // 如果是数组, 又没写[], 又不是最后一个元素, 就报错
                    LOG(ERROR) << "array expr do not have [] in middle key: " 
                        << build_xcharpos_str(&cur_key);
                    return -1;
                }

            }
            last_start_pos = pos+1;
        }
        if (c == '\0') {
            break;
        }
    }

    // 将结果字段输出
    *arr_len = result_arr_len;
    *field = result_field;
    return 0;
}

int xprotogetter::_get_simple_type_str(char * value_ptr, int type,
        string &result, bool json_format) {
    if (value_ptr == NULL) {
        return -1;
    }
    switch (type) {
        case XP_TYPE_INT:
            result = to_string(*(int *)value_ptr);
            return 0;
        case XP_TYPE_UINT:
            result = to_string(*(uint *)value_ptr);
            return 0;
        case XP_TYPE_INT64:
            result = to_string(*(int64_t *)value_ptr);
            return 0;
        case XP_TYPE_UINT64:
            result = to_string(*(uint64_t *)value_ptr);
            return 0;
        case XP_TYPE_INT8:
            result = to_string(*(int8_t *)value_ptr);
            return 0;
        case XP_TYPE_UINT8:
            result = to_string(*(uint8_t *)value_ptr);
            return 0;
        case XP_TYPE_INT16:
            result = to_string(*(int16_t *)value_ptr);
            return 0;
        case XP_TYPE_UINT16:
            result = to_string(*(uint16_t *)value_ptr);
            return 0;
        case XP_TYPE_FLOAT:
            result = to_string(*(float *)value_ptr);
            return 0;
        case XP_TYPE_DOUBLE:
            result = to_string(*(double *)value_ptr);
            return 0;
        case XP_TYPE_STRING:
            if (json_format) {
                result = "\"";
                to_json_str(value_ptr, result);
                result += "\"";
            } else {
                result = value_ptr;
            }
            return 0;
        default:
            return -1;
    }
    return 0;
}

/**
 * @brief 将该proto转换为json字符串输出
 *        输入可以是整个proto, 也可以是proto下面的要给object字段
 *
 * @param[in] handler 即该proto的句柄
 * @param[in] schema  该proto的描述schema文件
 * @param[out] result 输出最终结果的json
 *
 * @return 0 成功; 其他失败;
 */
int xprotogetter::get_object_json_str(int * handler, schema_t * schema, string &result) {
    result = "{";
    int idx_arr[1];
    for (int i=0; i<schema->fields_num; i++) {
        field_t * cur_field = schema->fields + i;
        idx_arr[0] = i;
        string tmp_result;
        int ret = get_field_json_str(handler, &idx_arr[0], 1, cur_field, tmp_result);
        if (ret == 0) {
            result += "\"";
            result += cur_field->name;
            result += "\": ";
            result += tmp_result + ",";
        }
    }
    // 将最后一个,给删除了
    if (result.size() > 1) {
        result.erase(result.size()-1);
    }
    result += "}";
    return 0;
}

/**
 * @brief 将该proto当中的指定的某个字段转化为json字符串返回
 *
 * @param[in] handler 二进制句柄
 * @param[in] idx_arr/arr_len 要转化的字段, 如果为NULL, 代表全部转化
 * @param[in] field 要转换的field的字段描述信息
 * @param[out] result 拼好的json
 *
 * @return 0成功; 其他失败
 */
int xprotogetter::get_field_json_str(int * handler, int * idx_arr, int arr_len, field_t * field, string &result) {
    int type = field->type;
    if (type == XP_TYPE_OBJECT) {
        // 对象类型
        int * cur_handler = o_n(handler, idx_arr, arr_len);
        if (cur_handler == NULL) {
            return -1;
        }
        return get_object_json_str(cur_handler, field->schema, result);
    } else if (type == XP_TYPE_ARRAY) {
        // 数组类型
        int element_type = field->element_type;
        int * cur_handler = o_n(handler, idx_arr, arr_len);
        if (cur_handler == NULL) {
            return -1;
        }
        int cur_arr_size = l0(cur_handler);
        if (cur_arr_size == 0) {
            // 没有元素, 直接返回了
            return -1;
        }
        if (element_type == XP_TYPE_OBJECT) {
            // 对象类型
            result = "[";
            for (int i=0; i<cur_arr_size; i++) {
                int * cur_obj_handler = o1(cur_handler, i);
                string tmp_result;
                int ret = get_object_json_str(cur_obj_handler, field->schema, tmp_result);
                if (ret == 0) {
                    result += tmp_result+",";
                }
            }
            // 将最后一个,给删除了
            if (result.size() > 1) {
                result.erase(result.size()-1);
            }
            result += "]";
            return 0;
        } else {
            // 普通类型
            result = "[";
            for (int i=0; i<cur_arr_size; i++) {
                string tmp_result;
                int ret = _get_simple_type_str(v1(cur_handler, i), element_type, tmp_result);
                if (ret == 0) {
                    result += tmp_result + ",";
                }
            }
            if (result.size() > 1) {
                result.erase(result.size()-1);
            }
            result += "]";
            return 0;
        }
    } else {
        // 普通类型
        char * value_ptr = v_n(handler, idx_arr, arr_len);
        return _get_simple_type_str(value_ptr, type, result);
    }
    return 0;
}

#endif
